home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / termsorc.lha / Extras / Source / term-source.lha / termARexx.c < prev    next >
C/C++ Source or Header  |  1995-09-26  |  19KB  |  1,057 lines

  1. /*
  2. **    termARexx.c
  3. **
  4. **    ARexx interface general support routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termARexxGlobal.h"
  11.  
  12.     /* IsNumeric(STRPTR String):
  13.      *
  14.      *    Is the string really a number?
  15.      */
  16.  
  17. BYTE __regargs
  18. IsNumeric(STRPTR String)
  19. {
  20.     while(*String && (*String == ' ' || *String == '\t'))
  21.         String++;
  22.  
  23.     while(*String)
  24.     {
  25.         if(*String < '0' || *String > '9')
  26.             return(FALSE);
  27.         else
  28.             String++;
  29.     }
  30.  
  31.     return(TRUE);
  32. }
  33.  
  34.     /* CreateResult(STRPTR ResultString,LONG *Results):
  35.      *
  36.      *    Create a proper Rexx result string.
  37.      */
  38.  
  39. STRPTR __regargs
  40. CreateResult(STRPTR ResultString,LONG *Results)
  41. {
  42.     STRPTR Result;
  43.  
  44.     if(!(Result = CreateArgstring(ResultString,strlen(ResultString))))
  45.     {
  46.         Results[0] = RC_ERROR;
  47.         Results[1] = ERROR_NO_FREE_STORE;
  48.     }
  49.  
  50.     return(Result);
  51. }
  52.  
  53.     /* CreateResultLen(STRPTR ResultString,LONG *Results):
  54.      *
  55.      *    Create a proper Rexx result string given the
  56.      *    length of the source string.
  57.      */
  58.  
  59. STRPTR __regargs
  60. CreateResultLen(STRPTR ResultString,LONG *Results,LONG Len)
  61. {
  62.     STRPTR Result;
  63.  
  64.     if(!(Result = CreateArgstring(ResultString,Len)))
  65.     {
  66.         Results[0] = RC_ERROR;
  67.         Results[1] = ERROR_NO_FREE_STORE;
  68.     }
  69.  
  70.     return(Result);
  71. }
  72.  
  73.     /* CreateVarArgs(STRPTR Value,struct RexxPkt *Packet,STRPTR Stem,...):
  74.      *
  75.      *    Set a Rexx variable, special treatment.
  76.      */
  77.  
  78. BYTE __stdargs
  79. CreateVarArgs(STRPTR Value,struct RexxPkt *Packet,STRPTR Stem,...)
  80. {
  81.     UBYTE    Name[256];
  82.     va_list    VarArgs;
  83.     LONG    Result;
  84.  
  85.     va_start(VarArgs,Stem);
  86.     VSPrintf(Name,Stem,VarArgs);
  87.     va_end(VarArgs);
  88.  
  89.     if(Result = SetRexxVar(Packet -> RexxMsg,Name,Value,strlen(Value)))
  90.     {
  91.         Packet -> Results[0] = RC_ERROR;
  92.         Packet -> Results[1] = Result;
  93.  
  94.         return(FALSE);
  95.     }
  96.     else
  97.         return(TRUE);
  98. }
  99.  
  100.     /* CreateVar(STRPTR Value,struct RexxPkt *Packet,STRPTR Name):
  101.      *
  102.      *    Set a Rexx variable, simple version.
  103.      */
  104.  
  105. STRPTR __regargs
  106. CreateVar(STRPTR Value,struct RexxPkt *Packet,STRPTR Name)
  107. {
  108.     LONG Result;
  109.  
  110.     if(Result = SetRexxVar(Packet -> RexxMsg,Name,Value,strlen(Value)))
  111.     {
  112.         Packet -> Results[0] = RC_ERROR;
  113.         Packet -> Results[1] = Result;
  114.     }
  115.  
  116.     return(NULL);
  117. }
  118.  
  119.     /* CreateMatchBuffer(STRPTR Pattern):
  120.      *
  121.      *    Create a pattern buffer suitable for pattern matching.
  122.      */
  123.  
  124. STRPTR __regargs
  125. CreateMatchBuffer(STRPTR Pattern)
  126. {
  127.     WORD    Len = strlen(Pattern) + 1;
  128.     STRPTR    Buffer;
  129.  
  130.     if(Buffer = (STRPTR)AllocVecPooled(2 * Len,MEMF_ANY))
  131.     {
  132.         if(ParsePatternNoCase(Pattern,Buffer,2 * Len) != -1)
  133.             return(Buffer);
  134.         else
  135.             FreeVecPooled(Buffer);
  136.     }
  137.  
  138.     return(NULL);
  139. }
  140.  
  141.     /* MatchBuffer(STRPTR Buffer,STRPTR Name):
  142.      *
  143.      *    Match a pattern against a string.
  144.      */
  145.  
  146. BYTE __regargs
  147. MatchBuffer(STRPTR Buffer,STRPTR Name)
  148. {
  149.     return((BYTE)MatchPatternNoCase(Buffer,Name));
  150. }
  151.  
  152.     /* DeleteMatchBuffer(STRPTR Buffer):
  153.      *
  154.      *    Free a pattern matching buffer.
  155.      */
  156.  
  157. VOID __regargs
  158. DeleteMatchBuffer(STRPTR Buffer)
  159. {
  160.     FreeVecPooled(Buffer);
  161. }
  162.  
  163.     /* ToMode(STRPTR Name):
  164.      *
  165.      *    Turn a transfer mode name into a key.
  166.      */
  167.  
  168. WORD __regargs
  169. ToMode(STRPTR Name)
  170. {
  171.     STATIC STRPTR TransferModes[] =
  172.     {
  173.         "BINARY",
  174.         "TEXT",
  175.         "ASCII",
  176.         NULL
  177.     };
  178.  
  179.     WORD i;
  180.  
  181.     for(i = 0 ; TransferModes[i] ; i++)
  182.     {
  183.         if(!Stricmp(Name,TransferModes[i]))
  184.             return(i);
  185.     }
  186.  
  187.     return(-1);
  188. }
  189.  
  190.     /* ToList(STRPTR Name):
  191.      *
  192.      *    Turn a list name into a key.
  193.      */
  194.  
  195. WORD __regargs
  196. ToList(STRPTR Name)
  197. {
  198.     STATIC STRPTR ListTypes[GLIST_COUNT] =
  199.     {
  200.         "UPLOAD",
  201.         "DOWNLOAD",
  202.         "DIAL",
  203.         "WAIT",
  204.         "TRAP"
  205.     };
  206.  
  207.     WORD i;
  208.  
  209.     for(i = 0 ; i < GLIST_COUNT ; i++)
  210.     {
  211.         if(!Stricmp(Name,ListTypes[i]))
  212.             return(i);
  213.     }
  214.  
  215.     return(-1);
  216. }
  217.  
  218.     /* ToConfig(STRPTR Name):
  219.      *
  220.      *    Turn a configuration name into a key.
  221.      */
  222.  
  223. WORD __regargs
  224. ToConfig(STRPTR Name)
  225. {
  226.     STATIC STRPTR DataTypes[DATATYPE_COUNT] =
  227.     {
  228.         "TRANSLATIONS",
  229.         "FUNCTIONKEYS",
  230.         "CURSORKEYS",
  231.         "FASTMACROS",
  232.         "HOTKEYS",
  233.         "SPEECH",
  234.         "SOUND",
  235.         "BUFFER",
  236.         "CONFIGURATION",
  237.         "PHONE",
  238.         "SCREENTEXT",
  239.         "SCREENIMAGE"
  240.     };
  241.  
  242.     WORD i;
  243.  
  244.     for(i = 0 ; i < DATATYPE_COUNT ; i++)
  245.     {
  246.         if(!Stricmp(Name,DataTypes[i]))
  247.             return(i);
  248.     }
  249.  
  250.     return(-1);
  251. }
  252.  
  253.     /* ToRequester(STRPTR Name):
  254.      *
  255.      *    Turn a requester name into a key.
  256.      */
  257.  
  258. WORD __regargs
  259. ToRequester(STRPTR Name)
  260. {
  261.     STRPTR RequesterTypes[REQUESTER_COUNT] =
  262.     {
  263.         "SERIAL",
  264.         "MODEM",
  265.         "SCREEN",
  266.         "TERMINAL",
  267.         "EMULATION",
  268.         "CLIPBOARD",
  269.         "CAPTURE",
  270.         "COMMANDS",
  271.         "MISC",
  272.         "PATH",
  273.         "TRANSFER",
  274.         "TRANSLATIONS",
  275.         "FUNCTIONKEYS",
  276.         "CURSORKEYS",
  277.         "FASTMACROS",
  278.         "HOTKEYS",
  279.         "SPEECH",
  280.         "SOUND",
  281.         "PHONE"
  282.     };
  283.  
  284.     WORD i;
  285.  
  286.     for(i = 0 ; i < REQUESTER_COUNT ; i++)
  287.     {
  288.         if(!Stricmp(Name,RequesterTypes[i]))
  289.             return(i);
  290.     }
  291.  
  292.     return(-1);
  293. }
  294.  
  295.     /* ToWindow(STRPTR Name):
  296.      *
  297.      *    Turn a window name into a key.
  298.      */
  299.  
  300. WORD __regargs
  301. ToWindow(STRPTR Name)
  302. {
  303.     STATIC STRPTR WindowTypes[WINDOWID_COUNT] =
  304.     {
  305.         "BUFFER",
  306.         "REVIEW",
  307.         "PACKET",
  308.         "FASTMACROS",
  309.         "STATUS",
  310.         "MAIN",
  311.         "UPLOADQUEUE",
  312.         "SINGLECHARENTRY"
  313.     };
  314.  
  315.     WORD i;
  316.  
  317.     for(i = 0 ; i < WINDOWID_COUNT ; i++)
  318.     {
  319.         if(!Stricmp(WindowTypes[i],Name))
  320.             return(i);
  321.     }
  322.  
  323.     return(-1);
  324. }
  325.  
  326.     /* ReplyRexxCommand():
  327.      *
  328.      *    Reply a command request the rexx server - or someone else -
  329.      *    has passed to us.
  330.      */
  331.  
  332. STATIC VOID __regargs
  333. ReplyRexxCommand(struct RexxMsg *RexxMessage,LONG Primary,LONG Secondary)
  334. {
  335.     if(RexxMessage)
  336.     {
  337.         RexxMessage -> rm_Result1 = Primary;
  338.         RexxMessage -> rm_Result2 = Secondary;
  339.  
  340.         ReplyMsg(RexxMessage);
  341.     }
  342. }
  343.  
  344.     /* RexxToolServer(VOID):
  345.      *
  346.      *    Asynchronous tool/rexx command execution process.
  347.      */
  348.  
  349. STATIC VOID __saveds
  350. RexxToolServer(VOID)
  351. {
  352.     struct Process    *ThisProcess = (struct Process *)SysBase -> ThisTask;
  353.     struct RexxPkt    *Packet;
  354.     BPTR         OldCOS,
  355.              NewCOS    = NULL;
  356.  
  357.         /* Wait for startup packet. */
  358.  
  359.     WaitPort(&ThisProcess -> pr_MsgPort);
  360.  
  361.     Packet = (struct RexxPkt *)GetMsg(&ThisProcess -> pr_MsgPort);
  362.  
  363.         /* Increment usage count. */
  364.  
  365.     ObtainSemaphore(&RexxLaunchSemaphore);
  366.  
  367.     RexxLaunchCount++;
  368.  
  369.     ReleaseSemaphore(&RexxLaunchSemaphore);
  370.  
  371.         /* Create proper output stream if necessary. */
  372.  
  373.     if(!ThisProcess -> pr_COS && ThisProcess -> pr_ConsoleTask)
  374.     {
  375.         if(NewCOS = Open("*",MODE_NEWFILE))
  376.         {
  377.             OldCOS = ThisProcess -> pr_COS;
  378.  
  379.             ThisProcess -> pr_COS = NewCOS;
  380.         }
  381.     }
  382.  
  383.         /* Execute the command. */
  384.  
  385.     (*Packet -> CommandInfo -> Routine)(Packet);
  386.  
  387.     Forbid();
  388.  
  389.         /* Decrement usage count. */
  390.  
  391.     ObtainSemaphore(&RexxLaunchSemaphore);
  392.  
  393.     RexxLaunchCount--;
  394.  
  395.     ReleaseSemaphore(&RexxLaunchSemaphore);
  396.  
  397.         /* Close the output stream. */
  398.  
  399.     if(NewCOS)
  400.     {
  401.         ThisProcess -> pr_COS = OldCOS;
  402.  
  403.         Close(NewCOS);
  404.     }
  405.  
  406.         /* Return the message packet. */
  407.  
  408.     ReplyMsg((struct Message *)Packet);
  409. }
  410.  
  411.     /* InvokeRexxCommand(struct RexxPkt *Packet):
  412.      *
  413.      *    Invoke an ARexx command.
  414.      */
  415.  
  416. STATIC BYTE __regargs
  417. InvokeRexxCommand(struct RexxPkt *Packet)
  418. {
  419.         /* Asynchronous command? */
  420.  
  421.     if(Packet -> CommandInfo -> Async)
  422.     {
  423.             /* Requires special execution code? */
  424.  
  425.         if(Packet -> CommandInfo -> Tool)
  426.         {
  427.             struct RexxPkt *NewPacket;
  428.  
  429.                 /* Create a command packet. */
  430.  
  431.             if(NewPacket = (struct RexxPkt *)AllocVecPooled(sizeof(struct RexxPkt),MEMF_ANY | MEMF_PUBLIC))
  432.             {
  433.                 enum    {    ARG_CONSOLE };
  434.  
  435.                 struct Process    *NewProcess;
  436.                 BPTR         Stream;
  437.  
  438.                     /* Set up the command packet. */
  439.  
  440.                 CopyMem(Packet,NewPacket,sizeof(struct RexxPkt));
  441.  
  442.                 NewPacket -> VanillaMessage . mn_ReplyPort    = RexxPort;
  443.                 NewPacket -> VanillaMessage . mn_Length        = sizeof(struct RexxPkt);
  444.  
  445.                     /* Create I/O streams. */
  446.  
  447.                 if(Packet -> Array[ARG_CONSOLE] && WindowName[0] && Packet -> CommandInfo -> Console)
  448.                     Stream = Open(WindowName,MODE_NEWFILE);
  449.                 else
  450.                     Stream = NULL;
  451.  
  452.                     /* Launch the process. */
  453.  
  454.                 if(Stream && GoodStream(Stream))
  455.                 {
  456.                     struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  457.  
  458.                     NewProcess = CreateNewProcTags(
  459.                         NP_Entry,    RexxToolServer,
  460.                         NP_Input,    Stream,
  461.                         NP_Output,    NULL,
  462.                         NP_ConsoleTask,    Handle -> fh_Type,
  463.                         NP_StackSize,    8000,
  464.                         NP_Name,    "term Rexx Tool Process",
  465.                         NP_Cli,        TRUE,
  466.                     TAG_DONE);
  467.                 }
  468.                 else
  469.                 {
  470.                     NewProcess = CreateNewProcTags(
  471.                         NP_Entry,    RexxToolServer,
  472.                         NP_StackSize,    8000,
  473.                         NP_ConsoleTask,    NULL,
  474.                         NP_Name,    "term Rexx Tool Process",
  475.                         NP_Cli,        TRUE,
  476.                     TAG_DONE);
  477.                 }
  478.  
  479.                     /* Send the command packet. */
  480.  
  481.                 if(NewProcess)
  482.                     PutMsg(&NewProcess -> pr_MsgPort,(struct Message *)NewPacket);
  483.                 else
  484.                 {
  485.                     FreeVecPooled(NewPacket);
  486.  
  487.                     ReplyRexxCommand(Packet -> RexxMsg,-1,0);
  488.  
  489.                     if(Stream)
  490.                         Close(Stream);
  491.                 }
  492.             }
  493.             else
  494.                 ReplyRexxCommand(Packet -> RexxMsg,-1,0);
  495.         }
  496.         else
  497.         {
  498.                 /* Execute the command on the schedule of the
  499.                  * rexx server process.
  500.                  */
  501.  
  502.             STRPTR Result = (*Packet -> CommandInfo -> Routine)(Packet);
  503.  
  504.             RexxPktCleanup(Packet,Result);
  505.         }
  506.     }
  507.     else
  508.     {
  509.         struct RexxPkt *NewPacket;
  510.  
  511.             /* Create message packet. */
  512.  
  513.         if(NewPacket = (struct RexxPkt *)AllocVecPooled(sizeof(struct RexxPkt),MEMF_ANY | MEMF_PUBLIC))
  514.         {
  515.                 /* Set up message packet. */
  516.  
  517.             CopyMem(Packet,NewPacket,sizeof(struct RexxPkt));
  518.  
  519.             NewPacket -> VanillaMessage . mn_ReplyPort    = RexxPort;
  520.             NewPacket -> VanillaMessage . mn_Length        = sizeof(struct RexxPkt);
  521.  
  522.                 /* Post it. */
  523.  
  524.             PutMsg(TermRexxPort,(struct Message *)NewPacket);
  525.         }
  526.         else
  527.             ReplyRexxCommand(Packet -> RexxMsg,-1,0);
  528.     }
  529.  
  530.     return(TRUE);
  531. }
  532.  
  533.     /* ParseRexxCommand(struct RexxMsg *RexxMsg):
  534.      *
  535.      *    Handles the synchronous Rexx commands and returns the
  536.      *    message if no matching command is found.
  537.      */
  538.  
  539. STATIC BYTE __regargs
  540. ParseRexxCommand(struct RexxMsg *RexxMsg)
  541. {
  542.     UBYTE    CommandBuffer[30];
  543.     STRPTR    Command,
  544.         CommandArgs;
  545.     LONG    Len = 0;
  546.  
  547.         /* Clear the local variables. */
  548.  
  549.     CommandBuffer[0]    = 0;
  550.     Command            = RexxMsg -> rm_Args[0];
  551.     CommandArgs        = NULL;
  552.  
  553.         /* Skip leading blank spaces. */
  554.  
  555.     while(*Command && (*Command == ' ' || *Command == '\t'))
  556.         Command++;
  557.  
  558.         /* Extract the command name. */
  559.  
  560.     do
  561.     {
  562.             /* Found the end of the string? */
  563.  
  564.         if(!Command[Len])
  565.         {
  566.                 /* Copy the command name. */
  567.  
  568.             strcpy(CommandBuffer,Command);
  569.  
  570.                 /* No arguments are provided. */
  571.  
  572.             CommandArgs = NULL;
  573.  
  574.             break;
  575.         }
  576.  
  577.             /* Found a blank space? */
  578.  
  579.         if(Command[Len] == ' ' || Command[Len] == '\t')
  580.         {
  581.                 /* Copy the command name. */
  582.  
  583.             memcpy(CommandBuffer,Command,Len);
  584.  
  585.             CommandBuffer[Len] = 0;
  586.  
  587.                 /* Look for any arguments. */
  588.  
  589.             CommandArgs = &Command[Len + 1];
  590.  
  591.                 /* Skip blank spaces. */
  592.  
  593.             while(*CommandArgs && (*CommandArgs == ' ' || *CommandArgs == '\t'))
  594.                 CommandArgs++;
  595.  
  596.             break;
  597.         }
  598.     }
  599.     while(++Len < 30);
  600.  
  601.         /* Did we find a command name? */
  602.  
  603.     if(CommandBuffer[0])
  604.     {
  605.         struct CommandInfo    *CommandInfo = NULL;
  606.         LONG             CommandIndex;
  607.  
  608.             /* Which command is it? */
  609.  
  610.         for(CommandIndex = 0 ; CommandIndex < CommandTableSize ; CommandIndex++)
  611.         {
  612.             if(!Stricmp(CommandBuffer,CommandTable[CommandIndex] . Name))
  613.             {
  614.                 CommandInfo = &CommandTable[CommandIndex];
  615.  
  616.                 break;
  617.             }
  618.         }
  619.  
  620.             /* Did we find the command? */
  621.  
  622.         if(CommandInfo)
  623.         {
  624.             struct RexxPkt __aligned    Packet;
  625.             BYTE                Processed = FALSE;
  626.  
  627.                 /* Set the result codes to defaults. */
  628.  
  629.             Packet . Results[0]    = RC_OK;
  630.             Packet . Results[1]    = 0;
  631.  
  632.                 /* Fill in the rest. */
  633.  
  634.             Packet . CommandInfo    = CommandInfo;
  635.             Packet . RexxMsg    = RexxMsg;
  636.  
  637.                 /* Does this command accept any arguments? */
  638.  
  639.             if(CommandInfo -> Arguments)
  640.             {
  641.                 LONG *Array;
  642.  
  643.                     /* Determine length of argument string. */
  644.  
  645.                 if(CommandArgs)
  646.                     Len = strlen(CommandArgs);
  647.                 else
  648.                     Len = 0;
  649.  
  650.                     /* Allocate temporary buffer, we will need to
  651.                      * attach a line-feed character to the argument
  652.                      * string.
  653.                      */
  654.  
  655.                 if(Array = (LONG *)AllocVecPooled(12 * sizeof(LONG) + Len + 2,MEMF_ANY | MEMF_CLEAR | MEMF_PUBLIC))
  656.                 {
  657.                     STRPTR         Buffer;
  658.                     struct RDArgs    *Args;
  659.  
  660.                         /* Get the argument buffer. */
  661.  
  662.                     Buffer = (STRPTR)&Array[12];
  663.  
  664.                         /* Copy the argument string. */
  665.  
  666.                     if(CommandArgs && Len)
  667.                         memcpy(Buffer,CommandArgs,Len);
  668.  
  669.                         /* Attach the line-feed character. */
  670.  
  671.                     Buffer[Len] = '\n';
  672.  
  673.                         /* Allocate argument parser data. */
  674.  
  675.                     if(Args = (struct RDArgs *)AllocDosObjectTags(DOS_RDARGS,TAG_DONE))
  676.                     {
  677.                         Packet . Array    = (STRPTR *)Array;
  678.                         Packet . Args    = Args;
  679.  
  680.                             /* Don't prompt for input! */
  681.  
  682.                         Args -> RDA_Flags |= RDAF_NOPROMPT;
  683.  
  684.                             /* Set up parser data. */
  685.  
  686.                         Args -> RDA_Source . CS_Buffer    = Buffer;
  687.                         Args -> RDA_Source . CS_Length    = Len + 1;
  688.                         Args -> RDA_Source . CS_CurChr    = 0;
  689.  
  690.                             /* Parse the arguments. */
  691.  
  692.                         if(ReadArgs(CommandInfo -> Arguments,Array,Args))
  693.                         {
  694.                             UWORD    Inclusion    = InclusionTable[CommandIndex];
  695.                             BYTE    ArgsRequired    = FALSE;
  696.                             WORD    i,Counted;
  697.  
  698.                                 /* Look for required arguments. */
  699.  
  700.                             for(i = Counted = 0 ; i < 12 ; i++)
  701.                             {
  702.                                 if(Inclusion & (1L << i))
  703.                                 {
  704.                                     ArgsRequired = TRUE;
  705.  
  706.                                     if(Array[i])
  707.                                         Counted++;
  708.                                 }
  709.                             }
  710.  
  711.                                 /* Are any arguments required
  712.                                  * but not provided?
  713.                                  */
  714.  
  715.                             if(ArgsRequired && !Counted)
  716.                             {
  717.                                 Packet . Results[0] = RC_ERROR;
  718.                                 Packet . Results[1] = ERROR_REQUIRED_ARG_MISSING;
  719.                             }
  720.                             else
  721.                             {
  722.                                 struct ExclusionInfo *Exclusion = ExclusionTable[CommandIndex];
  723.  
  724.                                     /* Any mutually-exclusive arguments? */
  725.  
  726.                                 if(Exclusion)
  727.                                 {
  728.                                     BYTE ArgsOkay = TRUE;
  729.  
  730.                                     i = 0;
  731.  
  732.                                         /* Look for arguments to
  733.                                          * exclude each other.
  734.                                          */
  735.  
  736.                                     while(ArgsOkay && Exclusion[i] . A != -1)
  737.                                     {
  738.                                         if(Array[Exclusion[i] . A] && Array[Exclusion[i] . B])
  739.                                             ArgsOkay = FALSE;
  740.                                         else
  741.                                             i++;
  742.                                     }
  743.  
  744.                                         /* All arguments correct? */
  745.  
  746.                                     if(ArgsOkay)
  747.                                         Processed = InvokeRexxCommand(&Packet);
  748.                                     else
  749.                                     {
  750.                                         Packet . Results[0] = RC_ERROR;
  751.                                         Packet . Results[1] = ERROR_TOO_MANY_ARGS;
  752.                                     }
  753.                                 }
  754.                                 else
  755.                                     Processed = InvokeRexxCommand(&Packet);
  756.                             }
  757.  
  758.                                 /* Free allocated parser data. */
  759.  
  760.                             if(!Processed)
  761.                                 FreeArgs(Args);
  762.                         }
  763.                         else
  764.                         {
  765.                             LONG Error = IoErr();
  766.  
  767.                             SetIoErr(Error);
  768.  
  769.                             Packet . Results[0] = RC_ERROR;
  770.                             Packet . Results[1] = IoErr();
  771.                         }
  772.  
  773.                             /* Free parser data. */
  774.  
  775.                         if(!Processed)
  776.                             FreeDosObject(DOS_RDARGS,Args);
  777.                     }
  778.                     else
  779.                     {
  780.                         Packet . Results[0] = RC_ERROR;
  781.                         Packet . Results[1] = ERROR_NO_FREE_STORE;
  782.                     }
  783.  
  784.                         /* Free temporary buffer. */
  785.  
  786.                     if(!Processed)
  787.                         FreeVecPooled(Array);
  788.                 }
  789.                 else
  790.                 {
  791.                     Packet . Results[0] = RC_ERROR;
  792.                     Packet . Results[1] = ERROR_NO_FREE_STORE;
  793.                 }
  794.             }
  795.             else
  796.             {
  797.                 Packet . Array    = NULL;
  798.                 Packet . Args    = NULL;
  799.  
  800.                 Processed = InvokeRexxCommand(&Packet);
  801.             }
  802.  
  803.             if(!Processed)
  804.             {
  805.                 if(Packet . Results[0] && Packet . Results[1])
  806.                     LastRexxError = Packet . Results[1];
  807.  
  808.                 ReplyRexxCommand(RexxMsg,Packet . Results[0],Packet . Results[1]);
  809.             }
  810.  
  811.             return(TRUE);
  812.         }
  813.     }
  814.  
  815.     return(FALSE);
  816. }
  817.  
  818.     /* RexxPktCleanup(struct RexxPkt *Packet,STRPTR Result):
  819.      *
  820.      *    Free the memory allocated for a message packet.
  821.      */
  822.  
  823. VOID __regargs
  824. RexxPktCleanup(struct RexxPkt *Packet,STRPTR Result)
  825. {
  826.     if(Packet -> Args)
  827.     {
  828.         FreeArgs(Packet -> Args);
  829.  
  830.         FreeDosObject(DOS_RDARGS,Packet -> Args);
  831.     }
  832.  
  833.     if(Packet -> Array)
  834.         FreeVecPooled(Packet -> Array);
  835.  
  836.     if(Packet -> Results[0])
  837.     {
  838.             /* Store error code. */
  839.  
  840.         if(Packet -> Results[1])
  841.         {
  842.             UBYTE Buffer[10];
  843.  
  844.             SPrintf(Buffer,"%ld",LastRexxError = Packet -> Results[1]);
  845.  
  846.             if(Packet -> RexxMsg)
  847.                 SetRexxVar(Packet -> RexxMsg,"TERM.LASTERROR",Buffer,strlen(Buffer));
  848.         }
  849.  
  850.         ReplyRexxCommand(Packet -> RexxMsg,Packet -> Results[0],Packet -> Results[1]);
  851.  
  852.         if(Result)
  853.             DeleteArgstring(Result);
  854.     }
  855.     else
  856.     {
  857.         if(Result)
  858.         {
  859.             if(Packet -> RexxMsg)
  860.             {
  861.                 if(Packet -> RexxMsg -> rm_Action & RXFF_RESULT)
  862.                     ReplyRexxCommand(Packet -> RexxMsg,0,(LONG)Result);
  863.                 else
  864.                 {
  865.                     DeleteArgstring(Result);
  866.  
  867.                     ReplyRexxCommand(Packet -> RexxMsg,0,0);
  868.                 }
  869.             }
  870.             else
  871.                 DeleteArgstring(Result);
  872.         }
  873.         else
  874.             ReplyRexxCommand(Packet -> RexxMsg,0,0);
  875.     }
  876. }
  877.  
  878.     /* RexxServer(VOID):
  879.      *
  880.      *    Asynchronous ARexx host server.
  881.      */
  882.  
  883. VOID __saveds
  884. RexxServer(VOID)
  885. {
  886.         /* Create the public host port. */
  887.  
  888.     if(RexxPort = CreateMsgPort())
  889.     {
  890.         struct RexxMsg    *RexxMsg;
  891.         ULONG         SignalSet;
  892.         BYTE         Done = FALSE;
  893.  
  894.         InitSemaphore(&RexxLaunchSemaphore);
  895.  
  896.         RexxPort -> mp_Node . ln_Name    = RexxPortName;
  897.         RexxPort -> mp_Node . ln_Pri    = 1;
  898.  
  899.             /* Make it a public port. */
  900.  
  901.         AddPort(RexxPort);
  902.  
  903.             /* Signal our father that we're running. */
  904.  
  905.         Signal(ThisProcess,SIG_HANDSHAKE);
  906.  
  907.             /* Go into loop and wait for input. */
  908.  
  909.         do
  910.         {
  911.             SignalSet = Wait(SIG_KILL | PORTMASK(RexxPort));
  912.  
  913.                 /* Are we to quit? */
  914.  
  915.             if(SignalSet & SIG_KILL)
  916.                 Done = TRUE;
  917.  
  918.                 /* This is probably a Rexx command. */
  919.  
  920.             if(SignalSet & PORTMASK(RexxPort))
  921.             {
  922.                     /* Pick up all the messages. */
  923.  
  924.                 while(RexxMsg = (struct RexxMsg *)GetMsg(RexxPort))
  925.                 {
  926.                         /* This is probably the reply to some
  927.                          * synchronous function invocation.
  928.                          */
  929.  
  930.                     if(RexxMsg -> rm_Node . mn_Node . ln_Type == NT_REPLYMSG)
  931.                         FreeVecPooled(RexxMsg);
  932.                     else
  933.                     {
  934.                             /* At first try to run the
  935.                              * command asynchronously.
  936.                              * If this turns out to be
  937.                              * somewhat `impossible' pass
  938.                              * it to the `term' main process
  939.                              * or - if in batch mode - try
  940.                              * to deal with the message
  941.                              * on our own.
  942.                              */
  943.  
  944.                         if(!ParseRexxCommand(RexxMsg))
  945.                         {
  946.                             UBYTE Buffer[10];
  947.  
  948.                             SPrintf(Buffer,"%ld",LastRexxError = TERMERROR_UNKNOWN_COMMAND);
  949.  
  950.                             SetRexxVar(RexxMsg,"TERM.LASTERROR",Buffer,strlen(Buffer));
  951.  
  952.                             ReplyRexxCommand(RexxMsg,RC_ERROR,TERMERROR_UNKNOWN_COMMAND);
  953.                         }
  954.                     }
  955.                 }
  956.             }
  957.         }
  958.         while(!Done);
  959.  
  960.         Done = FALSE;
  961.  
  962.             /* Process remaining messages. */
  963.  
  964.         do
  965.         {
  966.             while(RexxMsg = (struct RexxMsg *)GetMsg(RexxPort))
  967.             {
  968.                 if(RexxMsg -> rm_Node . mn_Node . ln_Type == NT_REPLYMSG)
  969.                     FreeVecPooled(RexxMsg);
  970.                 else
  971.                     ReplyRexxCommand(RexxMsg,-1,0);
  972.             }
  973.  
  974.             ObtainSemaphore(&RexxLaunchSemaphore);
  975.  
  976.             if(!RexxLaunchCount)
  977.             {
  978.                 Done = TRUE;
  979.  
  980.                 ReleaseSemaphore(&RexxLaunchSemaphore);
  981.             }
  982.             else
  983.             {
  984.                 ReleaseSemaphore(&RexxLaunchSemaphore);
  985.  
  986.                 WaitPort(RexxPort);
  987.             }
  988.         }
  989.         while(!Done);
  990.  
  991.         DeleteMsgPort(RexxPort);
  992.  
  993.         RexxPort = NULL;
  994.     }
  995.  
  996.     Forbid();
  997.  
  998.     RexxProcess = NULL;
  999.  
  1000.     Signal(ThisProcess,SIG_HANDSHAKE);
  1001. }
  1002.  
  1003.     /* HandleRexx():
  1004.      *
  1005.      *    Tiny & simple subroutine to read and examine all
  1006.      *    messages coming in to be processed synchronously
  1007.      *    by the `term' main process.
  1008.      */
  1009.  
  1010. BYTE
  1011. HandleRexx()
  1012. {
  1013.     struct RexxPkt *Packet;
  1014.  
  1015.         /* Obtain the message packet. */
  1016.  
  1017.     if(Packet = (struct RexxPkt *)GetMsg(TermRexxPort))
  1018.     {
  1019.         STRPTR Result;
  1020.  
  1021.         InRexx = TRUE;
  1022.  
  1023.         UpdateRequired = TransferUpdateRequired = FALSE;
  1024.  
  1025.             /* Execute the command. */
  1026.  
  1027.         Result = (*Packet -> CommandInfo -> Routine)(Packet);
  1028.  
  1029.             /* Free the packet data. */
  1030.  
  1031.         RexxPktCleanup(Packet,Result);
  1032.  
  1033.             /* Update the configuration if necessary. */
  1034.  
  1035.         if(UpdateRequired)
  1036.             ConfigSetup();
  1037.  
  1038.             /* Update the XPR options if necessary. */
  1039.  
  1040.         if(TransferUpdateRequired)
  1041.         {
  1042.             if(ProtocolSetup(TRUE))
  1043.                 SaveProtocolOpts();
  1044.         }
  1045.  
  1046.             /* Return the message packet. */
  1047.  
  1048.         ReplyMsg((struct Message *)Packet);
  1049.  
  1050.         InRexx = FALSE;
  1051.  
  1052.         return(TRUE);
  1053.     }
  1054.     else
  1055.         return(FALSE);
  1056. }
  1057.